package v2.creational.singleton;

/**
 * @author : zhenyun.su
 * @comment : 单实例 - 懒加载模式， 在需要使用对象时，才被创建
 *  基本原理：在使用时判断是否已经存在对象，若不存在对象则创建并返回；若已存在对象直接返回对象
 *  使用场景：适合所有场景，和预加载模式相比，性能慢点可忽略不计。 超高并发的化那就用预加载模式
 *
 * 下面通过二个方法，来构建最佳实践，参考LazyLoadSingleton
 * @since : 2019/8/19
 */

public class LazyLoadSingletonDemo {
    public static LazyLoadSingletonDemo instance;

    private LazyLoadSingletonDemo() {
    }

    // 方法1： 实现了单实例，但是线程不安全;
    // 原因：
    // 1. getInstance1()非原子性操作，
    // 2. new LazyLoadSingleton() 无法保证执行的顺序性
    // 初始化内存空间： memory= allocate();
    // 初始化对象： ctorInstance(memory);
    // 将对象内存地址赋值给变量： instance=memory();
    // 总结：  在new对象时，无法保证线程安全

    // 下面提供两个方法解决getInstance2() getInstance3()
    public static LazyLoadSingletonDemo getInstance1(){
        if (instance == null){
            instance= new LazyLoadSingletonDemo();
        }
        return instance;
    }

    // 方法2：实现线程安全，但是性能差
    // 添加synchronized关键字到getInstace()方法上确实保证了线程的安全
    // 但是每次调用getInstance()方法，不管有没有初始化实例，都会唤醒和阻塞线程，导致线程的上下文切换消耗大量时间
    // 解决方法： 在对象已经实例化后，就没有必要再使用synchronized加锁，直接返回对象。
    // 最佳实践： LazyLoadSingleton的getInstance()
    public static synchronized LazyLoadSingletonDemo getInstance2(){
        if (instance == null){
            instance= new LazyLoadSingletonDemo();
        }
        return instance;
    }

}
